package com.learn.english.service.impl;

import com.learn.english.mapper.MenuMapper;
import com.learn.english.model.entity.UserMenu;
import com.learn.english.model.ro.MenuRo;
import com.learn.english.service.IMenuService;
import com.learn.english.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author TISNIW
 * @version 1.0
 * @date 2025/6/21 20:58
 * @desc 菜单服务实现类
 */
@Slf4j
@Service
public class MenuServiceImpl implements IMenuService {
    @Autowired
    private RedisService redisService;
    @Autowired
    private MenuMapper menuMapper;

    @Override
    public String addMenu(UserMenu menu) {
        try {
            // 可以在这里加入权限校验等逻辑
            int result = menuMapper.insert(menu);
            if (result > 0) {
                return "菜单添加成功";
            } else {
                return "菜单添加失败";
            }
        } catch (Exception e) {
            log.error("添加菜单失败", e);
            return "菜单添加失败：" + e.getMessage();
        }
    }

    @Override
    public List<MenuRo> getMenu(int roleId, Integer type, Integer pageId) {
        try {
            // 1. 从数据库中根据 roleId 查询菜单列表
            log.info("getMenu: roleId={}, type={}, pageId={}", roleId, type, pageId);
            List<UserMenu> menus = menuMapper.selectByRoleId(roleId, type, pageId);
            if (menus == null || menus.isEmpty()) {
                return Collections.emptyList();
            }
            // 2. 构建菜单树
            return buildMenuTree(menus);
        } catch (Exception e) {
            log.error("获取菜单列表失败", e);
            return Collections.emptyList();
        }
    }

    @Override
    public List<UserMenu> getMenuTree(String name, Byte type, Byte status) {
        try {
            // 1. 查询所有菜单数据
            List<UserMenu> menus = menuMapper.selectByCondition(name, status);
            if (menus == null || menus.isEmpty()) {
                return Collections.emptyList();
            }
            
            // 2. 构建菜单树结构
            return buildUserMenuTree(menus);
        } catch (Exception e) {
            log.error("获取菜单树失败", e);
            return Collections.emptyList();
        }
    }

    @Override
    public String updateMenu(UserMenu menu) {
        try {
            int result = menuMapper.updateById(menu);
            if (result > 0) {
                return "菜单更新成功";
            } else {
                return "菜单更新失败";
            }
        } catch (Exception e) {
            log.error("更新菜单失败", e);
            return "菜单更新失败：" + e.getMessage();
        }
    }
    
    @Override
    public boolean hasChildren(Integer menuId) {
        try {
            return menuMapper.countChildren(menuId) > 0;
        } catch (Exception e) {
            log.error("检查菜单子项失败", e);
            return false;
        }
    }
    
    @Override
    public String deleteMenu(Integer menuId) {
        try {
            // 先检查是否有子菜单
            if (hasChildren(menuId)) {
                return "该菜单下还有子菜单，无法删除";
            }
            
            int result = menuMapper.deleteById(menuId);
            if (result > 0) {
                return "菜单删除成功";
            } else {
                return "菜单删除失败";
            }
        } catch (Exception e) {
            log.error("删除菜单失败", e);
            return "菜单删除失败：" + e.getMessage();
        }
    }
    
    @Override
    public String batchDeleteMenus(List<Integer> ids) {
        try {
            // 检查是否有菜单含有子菜单
            for (Integer id : ids) {
                if (hasChildren(id)) {
                    return "选择的菜单中包含有子菜单的项，无法批量删除";
                }
            }
            
            int result = menuMapper.deleteBatchIds(ids);
            if (result > 0) {
                return "批量删除菜单成功";
            } else {
                return "批量删除菜单失败";
            }
        } catch (Exception e) {
            log.error("批量删除菜单失败", e);
            return "批量删除菜单失败：" + e.getMessage();
        }
    }
    
    @Override
    public String updateMenuStatus(Integer menuId, Byte status) {
        try {
            UserMenu menu = new UserMenu();
            menu.setId(menuId);
            menu.setStatus(status);
            
            int result = menuMapper.updateById(menu);
            if (result > 0) {
                return "菜单状态更新成功";
            } else {
                return "菜单状态更新失败";
            }
        } catch (Exception e) {
            log.error("更新菜单状态失败", e);
            return "菜单状态更新失败：" + e.getMessage();
        }
    }

    /**
     * 构建MenuRo菜单树结构
     */
    private List<MenuRo> buildMenuTree(List<UserMenu> menus) {
        if (menus == null || menus.isEmpty()) return Collections.emptyList();

        Map<Integer, MenuRo> menuRoMap = new HashMap<>();
        Map<Integer, UserMenu> userMenuMap = new HashMap<>();
        List<MenuRo> rootMenus = new ArrayList<>();

        // 第一步：先缓存所有 UserMenu 到 map 中，方便查找
        for (UserMenu menu : menus) {
            if (menu.getId() != null) {
                userMenuMap.put(menu.getId(), menu);
            }
        }

        // 第二步：转换为 MenuRo 并建立父子关系
        for (UserMenu menu : menus) {
            if (menu.getId() == null) continue;

            Integer parentId = menu.getParentId();
            MenuRo currentMenu = convertToMenuRo(menu);

            // 缓存当前 MenuRo，防止重复创建
            menuRoMap.put(menu.getId(), currentMenu);

            if (parentId == null || parentId == 0) {
                rootMenus.add(currentMenu);
            } else {
                MenuRo parent = menuRoMap.get(parentId); // 直接从缓存中取
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    // 构建完整URL路径
                    if (parent.getUrl() != null && !parent.getUrl().endsWith("/")) {
                        currentMenu.setUrl(parent.getUrl() + "/" + menu.getUrl());
                    }
                    parent.getChildren().add(currentMenu);
                }
            }
        }

        return rootMenus;
    }
    
    /**
     * 构建UserMenu菜单树结构
     */
    private List<UserMenu> buildUserMenuTree(List<UserMenu> menus) {
        if (menus == null || menus.isEmpty()) return Collections.emptyList();
        
        Map<Integer, UserMenu> menuMap = new HashMap<>();
        List<UserMenu> rootMenus = new ArrayList<>();
        
        // 第一步：将所有菜单存入map中
        for (UserMenu menu : menus) {
            if (menu.getId() != null) {
                menuMap.put(menu.getId(), menu);
            }
        }
        
        // 第二步：构建父子关系
        for (UserMenu menu : menus) {
            if (menu.getId() == null) continue;
            
            Integer parentId = menu.getParentId();
            
            if (parentId == null || parentId == 0) {
                // 根菜单
                rootMenus.add(menu);
            } else {
                // 子菜单
                UserMenu parentMenu = menuMap.get(parentId);
                if (parentMenu != null) {
                    if (parentMenu.getChildren() == null) {
                        parentMenu.setChildren(new ArrayList<>());
                    }
                    parentMenu.getChildren().add(menu);
                    parentMenu.setHasChildren(true);
                }
            }
        }
        
        // 第三步：对每个菜单的子菜单进行排序
        sortMenuTree(rootMenus);
        
        return rootMenus;
    }
    
    /**
     * 递归排序菜单树
     */
    private void sortMenuTree(List<UserMenu> menus) {
        if (menus == null || menus.isEmpty()) return;
        
        // 按sort字段排序
        menus.sort(Comparator.comparing(UserMenu::getSort, Comparator.nullsLast(Integer::compareTo)));
        
        // 递归排序子菜单
        for (UserMenu menu : menus) {
            if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {
                sortMenuTree(menu.getChildren());
            }
        }
    }

    /**
     * 转换 UserMenu 到 MenuRo
     */
    private MenuRo convertToMenuRo(UserMenu menu) {
        return MenuRo.builder()
                .id(menu.getId())
                .name(menu.getName())
                .url(menu.getUrl())
                .icon(menu.getIcon())
                .type(menu.getType())
                .sort(menu.getSort())
                .build();
    }
}